package com.devilvan.betrice.douban.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.devilvan.betrice.common.BetriceResultCode;
import com.devilvan.betrice.common.BetriceResultVo;
import com.devilvan.betrice.douban.dto.DoubanMovieTop250Dto;
import com.devilvan.betrice.douban.po.DoubanMovieTop250Po;
import com.devilvan.betrice.douban.service.DoubanMovieTop250Service;
import com.devilvan.betrice.douban.mapper.DoubanMovieTop250Mapper;
import com.devilvan.betrice.douban.repository.DoubanMovieTop250Repository;
import com.devilvan.betrice.request.component.JsoupComponent;
import com.devilvan.betrice.util.UEmpty;
import com.devilvan.betrice.util.UCopy;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * @author Evad.Wu
 * @Description 豆瓣-电影前250名排行榜表 业务逻辑类
 * @date 2022-12-15
 */
@Service
public class DoubanMovieTop250ServiceImpl extends ServiceImpl<DoubanMovieTop250Mapper, DoubanMovieTop250Po> implements DoubanMovieTop250Service {
    private static final String DOUBAN_TOP250_URL_PREFIX = "https://movie.douban.com/top250";
    @Resource(name = "jsoupComponent")
    private JsoupComponent jsoupComponent;

    @Resource(name = "doubanMovieTop250Repository")
    private DoubanMovieTop250Repository doubanMovieTop250Repository;

    @Override
    public BetriceResultVo<DoubanMovieTop250Po> doDoubanMovieTop250Request() {
        Element body = jsoupComponent.parse("D:\\Mine\\Maven\\Betrice\\betrice-data-acquisition\\src\\main\\resources\\viewsource\\豆瓣250-网页源码.txt");
        BetriceResultVo<DoubanMovieTop250Po> betriceResultVo = this.doDoubanMovieTop250Parser(body);
        return betriceResultVo;
    }

    @Override
    public BetriceResultVo<DoubanMovieTop250Po> doDoubanMovieTop250Crawler(Map<String, String> subHeaders) {
        BetriceResultVo<DoubanMovieTop250Po> betriceResultVo = new BetriceResultVo<>();
        String url = DOUBAN_TOP250_URL_PREFIX;
        try {
            while (true) {
                Element body = jsoupComponent.getBody(url, subHeaders);
                this.doDoubanMovieTop250Parser(body);
                String nextPage = body.select("div.paginator>span.next>a").attr("href");
                if (UEmpty.isEmpty(nextPage)) {
                    break;
                }
                url = DOUBAN_TOP250_URL_PREFIX + nextPage;
                subHeaders.put("referer", url);
            }
            betriceResultVo.result(BetriceResultCode.SUCCESS_200, "操作成功！");
        } catch (Exception e) {
            e.printStackTrace();
            betriceResultVo.result(BetriceResultCode.FAILED_500, "操作失败！");
        }
        return betriceResultVo;
    }

    @Override
    public DoubanMovieTop250Po findByPid(Long pid) {
        LambdaQueryWrapper<DoubanMovieTop250Po> queryWrapper = new QueryWrapper<DoubanMovieTop250Po>().lambda();
        queryWrapper.eq(DoubanMovieTop250Po::getPid, pid);
        return this.getOne(queryWrapper);
    }


    @Override
    public DoubanMovieTop250Po saveUpdate(DoubanMovieTop250Dto doubanMovieTop250Dto) {
        DoubanMovieTop250Po doubanMovieTop250Po = new DoubanMovieTop250Po();
        UCopy.fullCopy(doubanMovieTop250Dto, doubanMovieTop250Po);
        return doubanMovieTop250Repository.saveAndFlush(doubanMovieTop250Po);
    }

    @Override
    public List<DoubanMovieTop250Po> saveUpdateBatch(List<DoubanMovieTop250Dto> list) {
        List<DoubanMovieTop250Po> doubanMovieTop250PoList = UCopy.fullCopyCollections(list, DoubanMovieTop250Po.class);
        return doubanMovieTop250Repository.saveAllAndFlush(doubanMovieTop250PoList);
    }

    /**
     * 豆瓣电影top250页面采集逻辑
     *
     * @param body 网页源码
     * @return 形式返回
     */
    private BetriceResultVo<DoubanMovieTop250Po> doDoubanMovieTop250Parser(Element body) {
        BetriceResultVo<DoubanMovieTop250Po> betriceResultVo = new BetriceResultVo<>();
        List<DoubanMovieTop250Po> doubanMovieTop250PoList = new ArrayList<>();
        Elements itemList = body.select("ol.grid_view>li>div.item");
        for (Element item : itemList) {
            Elements pic = item.select("div.pic");
            Integer movieRank = Integer.valueOf(pic.select("em").text());
            Element detailUrlPidImg = pic.select("a").first();
            String detailUrl = detailUrlPidImg.attr("href");
            Long pid = this.splitPid(detailUrl);
            String imgUrl = detailUrlPidImg.select("img").attr("src");
            Elements info = item.select("div.info");
            String name = info.select("div.hd>a>span.title").text().trim();
            String aliasName = info.select("div.hd>a>span.other").text().trim();
            Elements bd = info.select("div.bd");
            String bdp = bd.select("p:nth-child(1)").html().replaceAll("&nbsp;", "");
            String release = bdp.split("<br>")[1];
            String[] split = release.split("/");
            String releaseTime = null;
            String releaseDistrict = null;
            String kinds = null;
            for (int i = 0; i < split.length; i++) {
                if (i == 0) {
                    releaseTime = split[0].trim();
                } else if (i == 1) {
                    releaseDistrict = split[1].trim();
                } else if (i == 2) {
                    kinds = split[2].trim();
                }
            }
            Element bdStar = bd.select("div.star").first();
            String grade = bdStar.select("span:nth-child(2)").text();
            Integer commentSize = Integer.valueOf(bdStar.select("span:nth-child(4)").text().replace("人评价", ""));
            String quote = bd.select("p.quote>span.inq").text();
            DoubanMovieTop250Po doubanMovieTop250Po = new DoubanMovieTop250Po();
            doubanMovieTop250Po.setMovieRank(movieRank);
            doubanMovieTop250Po.setDetailUrl(detailUrl);
            doubanMovieTop250Po.setPid(pid);
            doubanMovieTop250Po.setImgUrl(imgUrl);
            doubanMovieTop250Po.setName(name);
            doubanMovieTop250Po.setAliasName(aliasName);
            doubanMovieTop250Po.setReleaseTime(releaseTime);
            doubanMovieTop250Po.setReleaseDistrict(releaseDistrict);
            doubanMovieTop250Po.setKinds(kinds);
            doubanMovieTop250Po.setGrade(grade);
            doubanMovieTop250Po.setCommentSize(commentSize);
            doubanMovieTop250Po.setQuote(quote);
            doubanMovieTop250PoList.add(doubanMovieTop250Po);
        }
        try {
            doubanMovieTop250Repository.saveAll(doubanMovieTop250PoList);
            betriceResultVo.result(BetriceResultCode.SUCCESS_200, "操作成功！");
        } catch (Exception e) {
            e.printStackTrace();
            betriceResultVo.result(BetriceResultCode.FAILED_500, "操作失败！");
        }
        return betriceResultVo;
    }


    /**
     * 从详情URL中分离出PID
     *
     * @param detailUrl 详情URL
     * @return PID
     */
    private Long splitPid(String detailUrl) {
        String regEx = "[^0-9]+";
        Pattern pattern = Pattern.compile(regEx);
        //用定义好的正则表达式拆分字符串，把字符串中的数字留出来
        String[] cs = pattern.split(detailUrl);
        return Long.valueOf(cs[1]);
    }
}
